using B.S.XZYData.Api.Wrter.Application.Command.WorkOrder;
using B.S.XZYData.Domain.LJC;
using B.S.XZYData.ErrorCode;
using B.S.XZYData.Infrastructure.Interface;
using MediatR;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Transactions;

namespace B.S.XZYData.Api.Wrter.Application.Handler.WorkOrder
{
    /// <summary>
    /// 保存工单处理器（主表+工序表+分派表一起保存）
    /// </summary>
    public class SaveWorkOrderHandler : IRequestHandler<SaveWorkOrderCommand, ApiResult<int>>
    {
        private readonly IBaseRepository<WorkOrderModel> _workOrderRepo;
        private readonly IBaseRepository<WorkOrderProcessModel> _workOrderProcessRepo;
        private readonly IBaseRepository<WorkOrderAssignModel> _workOrderAssignRepo;
        private readonly ILogger<SaveWorkOrderHandler> _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="workOrderRepo">工单仓储</param>
        /// <param name="workOrderProcessRepo">工单工序仓储</param>
        /// <param name="workOrderAssignRepo">工序分派仓储</param>
        /// <param name="logger">日志记录器</param>
        public SaveWorkOrderHandler(
            IBaseRepository<WorkOrderModel> workOrderRepo,
            IBaseRepository<WorkOrderProcessModel> workOrderProcessRepo,
            IBaseRepository<WorkOrderAssignModel> workOrderAssignRepo,
            ILogger<SaveWorkOrderHandler> logger)
        {
            _workOrderRepo = workOrderRepo;
            _workOrderProcessRepo = workOrderProcessRepo;
            _workOrderAssignRepo = workOrderAssignRepo;
            _logger = logger;
        }

        /// <summary>
        /// 保存工单
        /// </summary>
        /// <param name="request">命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>返回统一包装类</returns>
        public async Task<ApiResult<int>> Handle(SaveWorkOrderCommand request, CancellationToken cancellationToken)
        {
            var res = new ApiResult<int>();

            try
            {
                // 设置默认操作人，避免空值问题
                if (string.IsNullOrWhiteSpace(request.OperateBy))
                {
                    request.OperateBy = "System";
                }

                // 参数验证
                if (string.IsNullOrWhiteSpace(request.Code))
                {
                    res.Code = ApiEnum.Error;
                    res.Msg = "工单编号不能为空";
                    return res;
                }

                using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                {
                    WorkOrderModel workOrderModel;
                    int workOrderId;

                    if (request.Id > 0)
                    {
                        // 更新工单
                        workOrderModel = await _workOrderRepo.GetValue(request.Id);
                        if (workOrderModel == null)
                        {
                            res.Code = ApiEnum.Error;
                            res.Msg = "工单不存在";
                            return res;
                        }

                        // 检查工单编号是否被其他记录使用
                        var existingWorkOrder = _workOrderRepo.GetAll()
                            .Where(x => x.Code == request.Code && x.Id != request.Id).ToList().FirstOrDefault();
                        if (existingWorkOrder != null)
                        {
                            res.Code = ApiEnum.Error;
                            res.Msg = $"工单编号 {request.Code} 已存在，请使用其他编号";
                            return res;
                        }

                        // 更新工单信息
                        workOrderModel.Code = request.Code;
                        workOrderModel.PlanItemId = request.PlanItemId;
                        workOrderModel.RouteId = request.RouteId;
                        workOrderModel.ProductCode = request.ProductCode;
                        workOrderModel.ProductName = request.ProductName;
                        workOrderModel.Spec = request.Spec;
                        workOrderModel.Unit = request.Unit;
                        workOrderModel.PlannedQuantity = request.PlannedQuantity;
                        workOrderModel.ActualQuantity = request.ActualQuantity ?? 0;
                        workOrderModel.GoodQuantity = request.GoodQuantity ?? 0;
                        workOrderModel.BadQuantity = request.BadQuantity ?? 0;
                        workOrderModel.Status = request.Status;
                        workOrderModel.PlannedStartTime = request.PlannedStartTime;
                        workOrderModel.PlannedEndTime = request.PlannedEndTime;
                        // 实际时间设置为空值，后续通过其他方法更新
                        workOrderModel.ActualStartTime = request.ActualStartTime;
                        workOrderModel.ActualEndTime = request.ActualEndTime;
                        workOrderModel.Remark = request.Remark;
                        workOrderModel.UpdateBy = request.OperateBy;
                        workOrderModel.UpdateTime = DateTime.Now;

                        await _workOrderRepo.UpdateAsync(workOrderModel);
                        workOrderId = workOrderModel.Id;

                        _logger.LogInformation($"更新工单：{workOrderModel.Code}，操作人：{request.OperateBy}");
                    }
                    else
                    {
                        // 新增工单
                        // 检查工单编号是否已存在
                        var existingWorkOrder = _workOrderRepo.GetAll()
                            .Where(x => x.Code == request.Code).ToList().FirstOrDefault();
                        if (existingWorkOrder != null)
                        {
                            res.Code = ApiEnum.Error;
                            res.Msg = $"工单编号 {request.Code} 已存在，请使用其他编号";
                            return res;
                        }

                        workOrderModel = new WorkOrderModel
                        {
                            Code = request.Code,
                            PlanItemId = request.PlanItemId,
                            RouteId = request.RouteId,
                            ProductCode = request.ProductCode,
                            ProductName = request.ProductName,
                            Spec = request.Spec,
                            Unit = request.Unit,
                            PlannedQuantity = request.PlannedQuantity,
                            ActualQuantity = request.ActualQuantity ?? 0,
                            GoodQuantity = request.GoodQuantity ?? 0,
                            BadQuantity = request.BadQuantity ?? 0,
                            Status = request.Status ?? "未开始",
                            PlannedStartTime = request.PlannedStartTime,
                            PlannedEndTime = request.PlannedEndTime,
                            // 实际时间设置为空值，后续通过其他方法更新
                            ActualStartTime = request.ActualStartTime,
                            ActualEndTime = request.ActualEndTime,
                            Remark = request.Remark,
                            CreateBy = request.OperateBy,
                            CreateTime = DateTime.Now,
                            UpdateBy = request.OperateBy,
                            UpdateTime = DateTime.Now
                        };

                        workOrderId = await _workOrderRepo.CreateAsync(workOrderModel);

                        _logger.LogInformation($"新增工单：{workOrderModel.Code}，操作人：{request.OperateBy}");
                    }

                    // 处理工单工序
                    await ProcessWorkOrderProcesses(workOrderId, request.Processes, request.OperateBy);

                    scope.Complete();

                    res.Data = workOrderId;
                    res.Code = ApiEnum.Success;
                    res.Msg = request.Id > 0 ? "更新工单成功" : "新增工单成功";
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"保存工单失败，操作人：{request.OperateBy}");
                res.Code = ApiEnum.Error;
                res.Msg = $"保存工单失败：{ex.Message}";
            }

            return res;
        }

        /// <summary>
        /// 处理工单工序
        /// </summary>
        private async Task ProcessWorkOrderProcesses(int workOrderId, List<SaveWorkOrderProcessCommand> processes, string operateBy)
        {
            // 获取现有的工序
            var existingProcesses = _workOrderProcessRepo.GetAll()
                .Where(x => x.WorkOrderId == workOrderId)
                .ToList();

            // 处理需要删除的工序
            var processesToDelete = processes.Where(p => p.IsDeleted && p.Id > 0).ToList();
            foreach (var processToDelete in processesToDelete)
            {
                var existingProcess = existingProcesses.FirstOrDefault(x => x.Id == processToDelete.Id);
                if (existingProcess != null)
                {
                    // 先删除相关的分派记录
                    var existingAssigns = _workOrderAssignRepo.GetAll()
                        .Where(x => x.WorkOrderProcessId == existingProcess.Id)
                        .ToList();
                    foreach (var assign in existingAssigns)
                    {
                                                    await _workOrderAssignRepo.DeleteAsync(assign.Id);
                    }

                    await _workOrderProcessRepo.DeleteAsync(existingProcess.Id);
                    _logger.LogInformation($"删除工单工序：{existingProcess.ProcessName}，操作人：{operateBy}");
                }
            }

            // 处理需要新增或更新的工序
            var processesToSave = processes.Where(p => !p.IsDeleted).ToList();
            foreach (var processCommand in processesToSave)
            {
                WorkOrderProcessModel processModel;

                if (processCommand.Id > 0)
                {
                    // 更新工序
                    processModel = existingProcesses.FirstOrDefault(x => x.Id == processCommand.Id)!;
                    if (processModel != null)
                    {
                        processModel.Sequence = processCommand.Sequence;
                        processModel.ProcessCode = processCommand.ProcessCode;
                        processModel.ProcessName = processCommand.ProcessName;
                        processModel.PlannedQuantity = processCommand.PlannedQuantity ?? 0;
                        processModel.ReportedQuantity = processCommand.ReportedQuantity ?? 0;
                        processModel.GoodQuantity = processCommand.GoodQuantity ?? 0;
                        processModel.BadQuantity = processCommand.BadQuantity ?? 0;
                        processModel.Ratio = processCommand.Ratio;
                        processModel.PlannedStartTime = processCommand.PlannedStartTime;
                        processModel.PlannedEndTime = processCommand.PlannedEndTime;
                        // 实际时间设置为空值，后续通过其他方法更新
                        processModel.ActualStartTime = processCommand.ActualStartTime;
                        processModel.ActualEndTime = processCommand.ActualEndTime;
                        processModel.Status = processCommand.Status;
                        processModel.UpdateTime = DateTime.Now;

                        await _workOrderProcessRepo.UpdateAsync(processModel);
                        _logger.LogInformation($"更新工单工序：{processModel.ProcessName}，操作人：{operateBy}");
                    }
                }
                else
                {
                    // 新增工序
                    processModel = new WorkOrderProcessModel
                    {
                        WorkOrderId = workOrderId,
                        Sequence = processCommand.Sequence,
                        ProcessCode = processCommand.ProcessCode,
                        ProcessName = processCommand.ProcessName,
                        PlannedQuantity = processCommand.PlannedQuantity ?? 0,
                        ReportedQuantity = processCommand.ReportedQuantity ?? 0,
                        GoodQuantity = processCommand.GoodQuantity ?? 0,
                        BadQuantity = processCommand.BadQuantity ?? 0,
                        Ratio = processCommand.Ratio,
                        PlannedStartTime = processCommand.PlannedStartTime,
                        PlannedEndTime = processCommand.PlannedEndTime,
                        // 实际时间设置为空值，后续通过其他方法更新
                        ActualStartTime = processCommand.ActualStartTime,
                        ActualEndTime = processCommand.ActualEndTime,
                        Status = processCommand.Status ?? "未开始",
                        CreateTime = DateTime.Now,
                        UpdateTime = DateTime.Now
                    };

                    var processId = await _workOrderProcessRepo.CreateAsync(processModel);
                    processCommand.Id = processId; // 更新ID，用于处理分派

                    _logger.LogInformation($"新增工单工序：{processModel.ProcessName}，操作人：{operateBy}");
                }

                // 处理工序分派
                await ProcessWorkOrderAssigns(processCommand.Id, processCommand.Assigns, operateBy);
            }
        }

        /// <summary>
        /// 处理工序分派
        /// </summary>
        private async Task ProcessWorkOrderAssigns(int workOrderProcessId, List<SaveWorkOrderAssignCommand> assigns, string operateBy)
        {
            // 获取现有的分派
            var existingAssigns = _workOrderAssignRepo.GetAll()
                .Where(x => x.WorkOrderProcessId == workOrderProcessId)
                .ToList();

            // 处理需要删除的分派
            var assignsToDelete = assigns.Where(a => a.IsDeleted && a.Id > 0).ToList();
            foreach (var assignToDelete in assignsToDelete)
            {
                var existingAssign = existingAssigns.FirstOrDefault(x => x.Id == assignToDelete.Id);
                if (existingAssign != null)
                {
                                            await _workOrderAssignRepo.DeleteAsync(existingAssign.Id);
                    _logger.LogInformation($"删除工序分派：{existingAssign.EmployeeName}，操作人：{operateBy}");
                }
            }

            // 处理需要新增或更新的分派
            var assignsToSave = assigns.Where(a => !a.IsDeleted).ToList();
            foreach (var assignCommand in assignsToSave)
            {
                if (assignCommand.Id > 0)
                {
                    // 更新分派
                    var assignModel = existingAssigns.FirstOrDefault(x => x.Id == assignCommand.Id);
                    if (assignModel != null)
                    {
                        assignModel.EmployeeId = assignCommand.EmployeeId;
                        assignModel.EmployeeName = assignCommand.EmployeeName;
                        assignModel.Quantity = assignCommand.Quantity;
                        assignModel.UpdateTime = DateTime.Now;

                        await _workOrderAssignRepo.UpdateAsync(assignModel);
                        _logger.LogInformation($"更新工序分派：{assignModel.EmployeeName}，操作人：{operateBy}");
                    }
                }
                else
                {
                    // 新增分派
                    var assignModel = new WorkOrderAssignModel
                    {
                        WorkOrderProcessId = workOrderProcessId,
                        EmployeeId = assignCommand.EmployeeId,
                        EmployeeName = assignCommand.EmployeeName,
                        Quantity = assignCommand.Quantity,
                        CreateTime = DateTime.Now,
                        UpdateTime = DateTime.Now
                    };

                    await _workOrderAssignRepo.CreateAsync(assignModel);
                    _logger.LogInformation($"新增工序分派：{assignModel.EmployeeName}，操作人：{operateBy}");
                }
            }
        }
    }
}
